/*****************************************************************************
 * vtk_video_area.c : GTK+ Widget for VLC Gtkmm plugin
 *****************************************************************************/

#include "vtkvideoarea.h"

#include <gtk/gtkprivate.h>

/* Widget */

static void     vtk_video_area_class_init     (VtkVideoAreaClass *klass);
static void     vtk_video_area_realize        (GtkWidget *widget);
static gboolean vtk_video_area_expose         (GtkWidget *widget, GdkEventExpose *event);
static void     vtk_video_area_size_request   (GtkWidget *widget, GtkRequisition *requisition);
static void     vtk_video_area_paint          (GtkWidget *widget);
static void     vtk_video_area_init           (VtkVideoArea *area);

static void     vtk_video_area_set_property   (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void     vtk_video_area_get_property   (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);

static void     vtk_video_area_destroy    (GtkObject *object);

G_DEFINE_TYPE (VtkVideoArea, vtk_video_area, GTK_TYPE_WIDGET);

/* Private */
static gboolean cb_unset_size (gpointer data);
static void cb_set_preferred_size (GtkWidget *widget, GtkRequisition *req, gpointer data);

enum
{
  PROP_0,
  PROP_PIXBUF
};

static void
vtk_video_area_init (VtkVideoArea *area)
{

  area->logo = NULL;

} 


static void
vtk_video_area_class_init (VtkVideoAreaClass *klass)
{

  GObjectClass *gobject_class;
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  
  widget_class = GTK_WIDGET_CLASS (klass);

  widget_class->realize = vtk_video_area_realize;
  widget_class->expose_event = vtk_video_area_expose;
  widget_class->size_request = vtk_video_area_size_request;

  object_class = GTK_OBJECT_CLASS (klass);
  object_class->destroy = vtk_video_area_destroy;

  gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->set_property = vtk_video_area_set_property;
  gobject_class->get_property = vtk_video_area_get_property;

  g_object_class_install_property (gobject_class,
                                   PROP_PIXBUF,
                                   g_param_spec_object ("pixbuf",
                                                        "Pixbuf",
                                                        "A GdkPixbuf to display",
                                                        GDK_TYPE_PIXBUF,
                                                        GTK_PARAM_READWRITE));

}

static void 
vtk_video_area_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{

  VtkVideoArea *area;

  area = VTK_VIDEO_AREA (object);
  
  switch (prop_id)
    {
    case PROP_PIXBUF:
      vtk_video_area_set_pixbuf (area, g_value_get_object (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }

}

static void
vtk_video_area_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{

  VtkVideoArea *area;

  area = VTK_VIDEO_AREA (object);
  
  switch (prop_id)
    {
    case PROP_PIXBUF:
      g_value_set_object (value, vtk_video_area_get_pixbuf (area));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }

}

void
vtk_video_area_set_pixbuf (VtkVideoArea *area, GdkPixbuf *pixbuf)
{

  g_return_if_fail (VTK_IS_VIDEO_AREA (area));
  g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));

  g_object_freeze_notify (G_OBJECT (area));
  
  if (pixbuf != NULL)
    {
      g_object_ref (pixbuf);
      area->logo = pixbuf;
      vtk_video_area_paint (GTK_WIDGET (area));
    }

  g_object_notify (G_OBJECT (area), "pixbuf");
  
  g_object_thaw_notify (G_OBJECT (area));

}

GdkPixbuf*
vtk_video_area_get_pixbuf (VtkVideoArea *area)
{

  return area->logo;

}

static void
vtk_video_area_size_request (GtkWidget *widget, GtkRequisition *requisition)
{

  requisition->width = 0;
  requisition->height = 0;

  (void)widget;

}

static void
vtk_video_area_realize (GtkWidget *widget)
{

  GdkWindowAttr attributes;
  gint attributes_mask;
 	GdkColor color;

  g_return_if_fail (GTK_IS_WIDGET (widget));

  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = widget->allocation.x;
  attributes.y = widget->allocation.y;
  attributes.width = widget->allocation.width;
  attributes.height = widget->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = gtk_widget_get_events (widget);
  attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;

  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
  gdk_window_set_user_data (widget->window, widget);

  widget->style = gtk_style_attach (widget->style, widget->window);
  
  gdk_color_parse ("#000000", &color); // #000000 = black
	gdk_colormap_alloc_color (attributes.colormap, &color, TRUE, TRUE);
	gdk_window_set_background (widget->window, &color);

  vtk_video_area_set_preferred_size (VTK_VIDEO_AREA (widget), 240, 180);

}

static gboolean
vtk_video_area_expose (GtkWidget *widget, GdkEventExpose *event)
{

  g_return_val_if_fail (widget != NULL, TRUE);
  g_return_val_if_fail (VTK_IS_VIDEO_AREA (widget), TRUE);
  g_return_val_if_fail (event != NULL, TRUE);

  vtk_video_area_paint (widget);

  return FALSE;

}

static void
vtk_video_area_paint (GtkWidget *widget)
{

  GdkPixbuf *resize_pixbuf = NULL;
  int x;
  int y;
  int scale_x;
  int scale_y;

  if (!GTK_WIDGET_REALIZED (widget))
    return;

  gdk_window_clear_area (widget->window,
                         0,
                         0,
                         widget->allocation.width,
                         widget->allocation.height);

  if (VTK_VIDEO_AREA (widget)->logo != NULL)
   {
   
    scale_x =  gdk_pixbuf_get_width (VTK_VIDEO_AREA (widget)->logo);
    scale_y =  gdk_pixbuf_get_height (VTK_VIDEO_AREA (widget)->logo);

    x = scale_x * widget->allocation.height / scale_y;
    y = x * scale_y / scale_x;
   
    if (x > widget->allocation.width)
     {
      y = scale_y * widget->allocation.width / scale_x;
      x = scale_x * y / scale_y;
     }

    x *= 0.8;
    y *= 0.8;

    resize_pixbuf = gdk_pixbuf_scale_simple (VTK_VIDEO_AREA (widget)->logo, (x <= 0) ? 1 : x, (y <= 0) ? 1 : y, GDK_INTERP_BILINEAR);

    if (resize_pixbuf)                         
    gdk_pixbuf_render_to_drawable (resize_pixbuf,
                                   GDK_DRAWABLE (widget->window),
                                   NULL,
                                   0,
                                   0,
                                   widget->allocation.width / 2 - x / 2,
                                   widget->allocation.height / 2 - y / 2,
                                   x,
                                   y,
                                   GDK_RGB_DITHER_NORMAL,
                                   1, 
                                   1);

    g_object_unref (resize_pixbuf);

  }

}

GtkWidget*
vtk_video_area_new (GdkPixbuf *pixbuf)
{

  VtkVideoArea *area = g_object_new (VTK_TYPE_VIDEO_AREA, NULL);

  vtk_video_area_set_pixbuf (area, pixbuf);

  return GTK_WIDGET (area);

}

XID
vtk_video_area_get_xid (VtkVideoArea *area)
{

  return GDK_WINDOW_XID (GTK_WIDGET (area)->window);
         
}
              
static gboolean
cb_unset_size (gpointer data)
{

  GtkWidget *widget;
  
  widget = data;

  gtk_widget_queue_resize_no_redraw (widget);

  return FALSE;

}

static void
cb_set_preferred_size (GtkWidget *widget, GtkRequisition *req, gpointer data)
{

  AreaPrefSize *size;
  
  size = data;

  req->width = size->width;
  req->height = size->height;

  g_signal_handler_disconnect (widget, size->sig_id);
  g_idle_add (cb_unset_size, widget);

  g_free (size);

}

void
vtk_video_area_set_preferred_size (VtkVideoArea *area, gint width, gint height)
{

  AreaPrefSize *size;
  GtkWidget *widget;
  
  widget = GTK_WIDGET (area);
  
  size = g_new (AreaPrefSize, 1);

  size->width = width;
  size->height = height;
  size->sig_id = g_signal_connect (GTK_WIDGET (area),
                                   "size-request",
				                           G_CALLBACK (cb_set_preferred_size),
				                           size);

  gtk_widget_queue_resize (widget);

}

static void
vtk_video_area_destroy (GtkObject *object)
{
  
  VtkVideoArea *area;
  VtkVideoAreaClass *klass;

  area = VTK_VIDEO_AREA (object);

  if (area->logo != NULL)
   {
    g_object_unref (area->logo);
    area->logo = NULL;
   }

  klass = gtk_type_class (gtk_widget_get_type ());

  if (GTK_OBJECT_CLASS (klass)->destroy)
   {
     (* GTK_OBJECT_CLASS (klass)->destroy) (object);
   }

}

